﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RepositoryFramework
{
	/// <summary>
	/// Class <see cref="UnitOfWork"/> define unit of work
	/// </summary>
	public abstract class UnitOfWork<T> : IUnitOfWork, IDisposable where T : DbContext
	{
		#region Fields
		private readonly T _context;
		private bool _disposed = false;
		private DbContextTransaction _transaction = null;
		#endregion

		#region Properties
		/// <summary>
		/// Gets the unit of work context.
		/// </summary>
		/// <value>
		/// The context.
		/// </value>
		protected T Context
		{
			get { return _context; }
		}
		#endregion

		#region .ctor
		/// <summary>
		/// Initializes a new instance of the <see cref="UnitOfWork"/> class.
		/// </summary>
		public UnitOfWork(T entities)
		{
			if (entities == null)
			{
				throw new ArgumentNullException("entities");
			}
			_context = entities;
			_transaction = _context.Database.BeginTransaction();
		}
		#endregion

		#region Methods
		/// <summary>
		/// Commit changes
		/// </summary>
		public void Save()
		{
			try
			{
				_context.SaveChanges();
				_transaction.Commit();
			}
			catch
			{
				_transaction.Rollback();
				throw;
			}
			finally
			{
				_transaction = _context.Database.BeginTransaction();
			}

		}

		protected virtual void Dispose(bool disposing)
		{
			if (!this._disposed)
			{
				if (disposing)
				{
					_transaction.Dispose();
					_context.Dispose();
				}
			}
			this._disposed = true;
		}

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}
		#endregion

	}
}
